from tttdraw import TTTDraw, TicTacToe, TTTInput, GraphWin, time


def miniMax(ttt, depth=0):
    move = ()
    if ttt.isWin(3, 15, ttt.white):
        # print("-----", ttt.white)
        return -10 + depth, None
    if ttt.isWin(3, 15, ttt.black):
        # print("-----", ttt.white)
        return 10 - depth, None
    # 判断当前操作方
    if ttt.getPlayer() == TicTacToe.BLACK:
        bestValue = -100
        # 获取当前状态下的可执行节点
        for child in ttt.getAllMoves():
            # 对当前节点进行克隆
            new_ttt = ttt.clone()
            # 对当前节点进行操作
            new_ttt.play(*child)
            # 获取节点下的权值
            v, _ = miniMax(new_ttt, depth - 1)
            # 如果最优值比返回值小，那么说明返回值为最优值
            if bestValue < v:
                # 重新选择最优值
                bestValue = v
                # 则最优值时的可移动节点
                move = child
            # bestValue = max(bestValue, v)
            # move = child
        return bestValue, move
    else:
        bestValue = 100
        # 获取当前状态下的可执行节点
        for child in ttt.getAllMoves():
            # 对当前节点进行移动
            new_ttt = ttt.clone()
            # 对当前节点进行操作
            new_ttt.play(*child)
            # 获取节点下的权值
            v, _ = miniMax(new_ttt, depth - 1)
            # 如果最优值比返回值大，那么说明返回值为最优值
            if bestValue > v:
                # 重新选择最优值
                bestValue = v
                # 则最优值时的可移动节点
                move = child
            # bestValue = min(bestValue, v)
            # move = child
        return bestValue, move
    return bestValue, move


def main():
    win = GraphWin('miniMax - 董尧', 600, 600, autoflush=False)
    ttt = TicTacToe()
    tttdraw = TTTDraw(win)
    tttinput = TTTInput(win)

    # BLACK 主动方
    while win.checkKey() != 'Escape':
        if ttt.getPlayer() == TicTacToe.WHITE:
            t1 = time.perf_counter()
            v, move = miniMax(ttt)
            t2 = time.perf_counter()
            print("搜索耗时", t2 - t1)
            if move != ():
                ttt.play(*move)
        tttinput.input(ttt)
        tttdraw.draw(ttt)
        if ttt.isGameOver() is not None:
            time.sleep(5)
            ttt.reset()
            # win.getMouse()
    win.close()


if __name__ == '__main__':
    main()
